package com.common.auth.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.common.api.exception.CommonException;
import com.common.auth.api.dto.ResourceDto;
import com.common.auth.api.service.ResourceService;
import com.common.auth.api.service.RoleResourceService;
import com.common.auth.po.ResourcePo;
import com.common.auth.po.RoleResourcePo;
import com.common.util.GenerateSequenceUtil;

import cn.hutool.core.lang.Assert;

/**
 * <p>
 * 资源服务实现类
 * </p>
 *
 * @author ficus
 */
@Service
public class ResourceServiceImpl extends ResourceService {

	@Autowired
	private RoleResourceService roleResourceService;
	
	@Transactional()
	@Override
	public void deleteMenuById(String resourceId) {
		Assert.notBlank(resourceId, ()-> new CommonException("资源id不能为空!"));
		ResourcePo po = getById(resourceId);
		Assert.notNull(po, ()-> new CommonException("根据资源ID"+resourceId+"查询对象不存在!"));
		boolean existChild = getBaseMapper().exists(Wrappers.lambdaQuery(ResourcePo.class)
				.eq(ResourcePo::getParentCode, po.getResourceCode()));
		Assert.isTrue(existChild, ()-> new CommonException("当前要删除的菜单存在子菜单，请先删除子菜单!"));
		// 删除当前菜单
		removeById(resourceId);
		// 删除菜单关联的角色
		roleResourceService.remove(Wrappers.lambdaQuery(RoleResourcePo.class)
				.eq(RoleResourcePo::getResourceCode, po.getResourceCode()));
		
	}

	@Override
	public int saveDto(ResourceDto dto) {
		String id =  dto.getId();
		if(StringUtils.isEmpty(id)) {
			dto.setId(GenerateSequenceUtil.generateSequenceNo());
			dto.setCreateTime(new Date());
		}
		dto.setUpdateTime(new Date());
		return super.saveDto(dto);
	}
	
	@Override
	public List<ResourceDto> queryTreeList() {
		List<ResourcePo> resourcePoList=list();
		List<ResourceDto> rootList=buildResourceTress(resourcePoList);
		return rootList;
	}

	@Override
	public List<ResourceDto> queryTreeList(List<String> resourceCodeList) {
		List<ResourcePo> resourcePoList=list(Wrappers.lambdaQuery(ResourcePo.class).in(ResourcePo::getResourceCode, resourceCodeList));
		List<ResourceDto> rootList=buildResourceTress(resourcePoList);
		return rootList;
	}

	@Override
	public String getOrderBy() {
		return "sort_no";
	}
	
	@Override
	public List<String> getSearchKeyList() {
		return Arrays.asList("resource_code","resource_name");
	}
	
	
	private List<ResourceDto> buildResourceTress(List<ResourcePo> resourcePoList){
		List<ResourceDto> rootList=new ArrayList<ResourceDto>();
		Map<String,List<ResourceDto>> parentMap=new HashMap<>();
		resourcePoList.forEach(item->{
			ResourceDto resourceDto=convertToDto(item,ResourceDto.class);
			String extInfo=resourceDto.getExtInfo();
			if(StringUtils.isEmpty(extInfo)) {
				resourceDto.setExtInfoObj(new Object());
			} else {
				JSONObject jsonObj=JSON.parseObject(extInfo);
				resourceDto.setExtInfoObj(jsonObj);
			}
			resourceDto.setChildren(new ArrayList<>());
			String parentCode=item.getParentCode();
			if(StringUtils.isEmpty(parentCode)) {
				rootList.add(resourceDto);
			}else {
				List<ResourceDto> subList=parentMap.get(parentCode);
				if(subList==null) {
					subList=new ArrayList<>();
					parentMap.put(parentCode, subList);
				}
				subList.add(resourceDto);
			}
		});
		// 生成子节点数据
		rootList.forEach(resourceDto->{
			addSubList(resourceDto,parentMap);
		});
		return rootList;
	}
	
	// 循环调用生成子节点数据
	private void addSubList(ResourceDto parentDto,Map<String,List<ResourceDto>> parentMap) {
		String parentCode=parentDto.getResourceCode();
		List<ResourceDto> subList=parentMap.get(parentCode);
		if(CollectionUtils.isEmpty(subList)) {
			return;
		}
		parentDto.getChildren().addAll(subList);
		subList.forEach(subItem->{
			addSubList(subItem,parentMap);
		});
	}
}
